<?php

namespace yifang\model;

use yifang\db\Collection as BaseCollection;
use yifang\model\Model;
use yifang\db\Paginator;


/**
 * 模型数据集类
 */
class Collection extends BaseCollection
{
    /**
     * 延迟预载入关联查询
     */
    public function load($relation, $cache = false)
    {
        if (!$this->isEmpty()) {
            $item = current($this->items);
            $item->eagerlyResultSet($this->items, (array) $relation, [], false, $cache);
        }
        return $this;
    }

    /**
     * 删除数据集的数据
     */
    public function delete()
    {
        $this->each(function (Model $model) {
            $model->delete();
        });
        return true;
    }

    /**
     * 更新数据
     */
    public function update(array $data, array $allowField = [])
    {
        $this->each(function (Model $model) use ($data, $allowField) {
            if (!empty($allowField)) {
                $model->allowField($allowField);
            }
            $model->save($data);
        });
        return true;
    }

    /**
     * 设置需要隐藏的输出属性
     */
    public function hidden(array $hidden, $merge = false)
    {
        $this->each(function (Model $model) use ($hidden, $merge) {
            $model->hidden($hidden, $merge);
        });
        return $this;
    }

    /**
     * 设置需要输出的属性
     */
    public function visible(array $visible,$merge = false)
    {
        $this->each(function (Model $model) use ($visible, $merge) {
            $model->visible($visible, $merge);
        });
        return $this;
    }

    /**
     * 设置需要追加的输出属性
     */
    public function append(array $append,$merge = false)
    {
        $this->each(function (Model $model) use ($append, $merge) {
            $model->append($append, $merge);
        });
        return $this;
    }

    /**
     * 设置模型输出场景
     */
    public function scene($scene)
    {
        $this->each(function (Model $model) use ($scene) {
            $model->scene($scene);
        });
        return $this;
    }

    /**
     * 设置父模型
     */
    public function setParent(Model $parent)
    {
        $this->each(function (Model $model) use ($parent) {
            $model->setParent($parent);
        });
        return $this;
    }

    /**
     * 设置数据字段获取器
     */
    public function withAttr($name, $callback = null)
    {
        $this->each(function (Model $model) use ($name, $callback) {
            $model->withAttr($name, $callback);
        });
        return $this;
    }

    /**
     * 绑定（一对一）关联属性到当前模型
     */
    public function bindAttr($relation, array $attrs = [])
    {
        $this->each(function (Model $model) use ($relation, $attrs) {
            $model->bindAttr($relation, $attrs);
        });
        return $this;
    }

    /**
     * 按指定键整理数据
     */
    public function dictionary($items = null, &$indexKey = null)
    {
        if ($items instanceof self || $items instanceof Paginator) {
            $items = $items->all();
        }
        $items = is_null($items) ? $this->items : $items;
        if ($items && empty($indexKey)) {
            $indexKey = $items[0]->getPk();
        }
        if (isset($indexKey) && is_string($indexKey)) {
            return array_column($items, null, $indexKey);
        }
        return $items;
    }

    /**
     * 比较数据集，返回差集
     */
    public function diff($items, $indexKey = null)
    {
        if ($this->isEmpty()) {
            return new static($items);
        }
        $diff       = [];
        $dictionary = $this->dictionary($items, $indexKey);
        if (is_string($indexKey)) {
            foreach ($this->items as $item) {
                if (!isset($dictionary[$item[$indexKey]])) {
                    $diff[] = $item;
                }
            }
        }
        return new static($diff);
    }

    /**
     * 比较数据集，返回交集
     */
    public function intersect($items, $indexKey = null)
    {
        if ($this->isEmpty()) {
            return new static([]);
        }
        $intersect  = [];
        $dictionary = $this->dictionary($items, $indexKey);
        if (is_string($indexKey)) {
            foreach ($this->items as $item) {
                if (isset($dictionary[$item[$indexKey]])) {
                    $intersect[] = $item;
                }
            }
        }
        return new static($intersect);
    }
}
